/*
 * DrawController.h
 *
 *  Created on: Oct 7, 2011
 *      Author: erudhes
 */

#ifndef DYNAMICDRAWCONTROLLER_H_
#define DYNAMICDRAWCONTROLLER_H_
#include <wx/wx.h>
#include "StaticDrawController.h"
#include "WxUtils.h"

/**
 * This class handles the drawing during the gameplay
 *
 * The class handles every kind of dynamic drawing, the movement of the vehicles and the redrawn of the level if needed
 * @author Rudolf Heszele heszele@gmail.com
 * @version 1.0
 * @since 2012-03-08
 */
class DynamicDrawController: public StaticDrawController
{
	public:
		/**
		 * The only constructor takes every parameter which is needed for the drawing
		 *
		 * For every turn a new object is created to handle the drawing. This is why we need a lot of parameters here.
		 * These parameters are maintained during the whole gameplay not just for one turn, so they are given from one
		 * object to an other in every new turn.
		 * @param bitmap The bitmap to do the drawings on
		 * @param originalLvevel The bitmap containing the original level - without any dynamic drawing. Used to restore the level
		 * @param actualVehicle The vehicle which is active in the current turn
		 * @param remoteVehicle The vehicle which is inactive in the current turn
		 * @param actualVehicleArrows An array of points, containing the earlier positions of the actual vehicle
		 * @param remoteVehicleArrows An array of points, containing the earlier positions of the remote vehicle
		 * @param firstStep Contains the first step of the actual vehicle or WxUtils::INVALID_POINT at the beginning
		 */
		DynamicDrawController(SmartPointer<wxBitmap> bitmap, SmartPointer<wxImage> originalLevel,
							  SmartPointer<Vehicle> actualVehicle, SmartPointer<Vehicle> remoteVehicle,
							  SmartPointer<std::vector<wxPoint> > actualVehicleArrows,
							  SmartPointer<std::vector<wxPoint> > remoteVehicleArrows, const wxPoint& firstStep);
		virtual ~DynamicDrawController();

		// Methods inherited from IController

		/**
		 * @see IController::handleMouseDown
		 */
		virtual void handleMouseDown(const wxPoint& position);
		/**
		 * @see IController::handleMouseUp
		 */
		virtual void handleMouseUp(const wxPoint& position);
		/**
		 * @see IController::handleMouseMotion
		 */
		virtual bool handleMouseMotion(const wxPoint& position);

		// Methods inherited from IDrawController

		/**
		 * @see IDrawController::getActualVehicle
		 */
		virtual SmartPointer<Vehicle> getActualVehicle() const;
		/**
		 * @see IDrawController::getRemoteVehicle
		 */
		virtual SmartPointer<Vehicle> getRemoteVehicle() const;
		/**
		 * @see IDrawController::getActualVehicleArrows
		 */
		virtual SmartPointer<std::vector<wxPoint> > getActualVehicleArrows();
		/**
		 * @see IDrawController::getRemoteVehicleArrows
		 */
		virtual SmartPointer<std::vector<wxPoint> > getRemoteVehicleArrows();

		// Own methods

		const wxPoint& getFirstStep();

	private:
		/**
		 * This method calculates the nearest dot to the given position
		 *
		 * @param position The position the method needs to calculate against
		 * @return The coordinates of the nearest dot
		 */
		wxPoint getNearestDot(const wxPoint& position) const;
		/**
		 * This method calculates the nearest valid dot to the given position
		 *
		 * The valid dots are the calculated based on the next position of the actual vehicle.
		 * Additional check is made to ensure the points are inside the level.
		 * @param position The position the method needs to calculate against
		 * @return The coordinates of the nearest valid dot
		 */
		wxPoint getNearestValidDot(const wxPoint& position) const;
		/**
		 * This method initializes the member variable containing all the available valid dots
		 */
		void getValidDotsInsideLevel();
		/**
		 * This method erases or highlights the valid dots during the gameplay
		 *
		 * @param erase If it is true the valid dots will be erased, if false they will be highlighted
		 */
		void highlightOrEraseValidDots(bool erase);
		/**
		 * Helper method to align the given dot, to make it valid - inside the level.
		 */
		void alignDot(wxPoint& dot) const;
		/**
		 * Helper method to calculate the smallest rect, which can include all the given points
		 *
		 * @param points List of points which ones must be inside the rect
		 * @return The wxRect which can contain all the points
		 */
		wxRect getSmallestContainingRect(const std::vector<wxPoint>& points) const;
		/**
		 * Helper method to check the color of the original level on the given coordination
		 *
		 * @see WxUtils::Color
		 * @param x The x coordinate
		 * @param y The y coordinate
		 * @param color The expected color of the pixel
		 * @return true if the pixel on the given coordinate is in the expected color, false otherwise
		 */
		bool checkColor(int x, int y, const WxUtils::Color& color) const;
		/**
		 * Helper method to redraw the whole way of the vehicles
		 *
		 * @see wxDC
		 * @param arrows List of points containing the previous positions of the car
		 * @param dc The device controller for painting
		 */
		void redrawArrows(std::vector<wxPoint>* arrows, wxDC& dc);
		/**
		 * Helper method to check if the game is finished or not
		 *
		 * @param nexPosition The next position of the actual vehicle
		 * @return true if the actual vehicle finished the turn or crashed
		 */
		bool isGameFinished(const wxPoint& nextPosition);
		/**
		 * Helper method to decide if the actual vehicle is in one line with the starting line
		 *
		 * @param nextPosition The next position of the actual vehicle
		 * @return true if the vehicle in one line with the starting line, false otherwise
		 */
		bool isTheActualVehicleInTheStartingLine(const wxPoint& nextPosition);

		/**
		 * Stores the original level, for level restoring during the game
		 */
		SmartPointer<wxImage> mOriginalLevel;
		/**
		 * Stores the earlier highlighted dot, to be able to erase the highlighting
		 */
		wxPoint mEarlierHighlightedDot;
		/**
		 * Stores the earlier end point of the drawn array, needed to be able to erase it
		 */
		wxPoint mEarlierEndPoint;
		/**
		 * Contains the first step of the actual vehicle, needed to determine the finishing conditions
		 */
		wxPoint mFirstStep;
		/**
		 * Stores the actual vehicle- which one will move in the current turn
		 */
		SmartPointer<Vehicle> mActualVehicle;
		/**
		 * Stores the remote vehicle
		 */
		SmartPointer<Vehicle> mRemoteVehicle;
		/**
		 * Earlier positions of the actual vehicle, needed for redrawn its way
		 */
		SmartPointer<std::vector<wxPoint> > mActualVehicleArrows;
		/**
		 * Earlier positions of the remote vehicle, needed for redrawn its way
		 */
		SmartPointer<std::vector<wxPoint> > mRemoteVehicleArrows;
		/**
		 * List of valid dots inside the level. Calculated during object creation
		 */
		std::vector<wxPoint> mValidDotsInsideLevel;
		/**
		 * True if the mouse down is clicked
		 */
		bool mIsMouseButtonDown;
		/**
		 * true if the vehicle crossed the start line, but from a wrong direction. Needed to determine the finishing conditions
		 */
		bool mIsCrossedStartLine;
};

inline const wxPoint& DynamicDrawController::getFirstStep()
{
	return mFirstStep;
}

#endif /* DYNAMICDRAWCONTROLLER_H_ */
